#include "../inc/segment.h"

int Segment::counter = 0;

Segment::Segment()
{
	id = counter;
	depth = 0;
	verts.clear();
	counter++;
}

Segment::Segment(const Segment &_s)
{
	id = _s.id;
	depth = _s.depth;
	verts.clear();
	verts = _s.verts;
	/* Shal the counter really be incremented in the copy constructor ? */
	counter++;
}

Segment::~Segment()
{
	verts.clear();
}

Segment& Segment::operator = ( const Segment& _s )
{
	id = _s.id;
	depth = _s.depth;
	verts.clear();
	verts = _s.verts;
	
	return *this;
}

Segment& Segment::operator +( const Segment& _s )
{
	list<Vertex*> cpy = _s.verts;
	
	for ( list<Vertex*>::iterator it = cpy.begin() ; it != cpy.end() ; it++ )
		addVert( (*it) );
	
	return *this;
}

Segment& Segment::operator +( const Segment*& _s )
{
	list<Vertex*> cpy = _s->verts;
	
	for ( list<Vertex*>::iterator it = cpy.begin() ; it != cpy.end() ; it++ )
		addVert( (*it) );
	
	return *this;
}

Segment& Segment::operator += ( const Segment& _s )
{
	list<Vertex*> cpy = _s.verts;
	
	for ( list<Vertex*>::iterator it = cpy.begin() ; it != cpy.end() ; it++ )
		addVert( (*it) );
	
	return *this;
}

Segment& Segment::operator += ( const Segment*& _s )
{
	list<Vertex*> cpy = _s->verts;
	
	for ( list<Vertex*>::iterator it = cpy.begin() ; it != cpy.end() ; it++ )
		addVert( (*it) );
	
	return *this;
}

int Segment::getID()
{
	return id;
}

double Segment::getDepth()
{
	return depth;
}

list<Vertex*> Segment::getVerts()
{
	return verts;
}

void Segment::setID(int _ID)
{
	id = _ID;
}

void Segment::setDepth(double _depth)
{
	depth = _depth;
}

void Segment::setVerts(list<Vertex *> _v)
{
	verts = _v;
}

list<Vertex*> Segment::getBoundary()
{
	list<Vertex*> rslt;
	
	/* We look at every vertices of the segment. */
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
		/* This boolean is created in order to avoid adding several times the same vertex to the rslt list. */
		bool done = false;
		
		/* If one neighbour of the vertex is not a part of the segment, it is a boundary vertex and we add it to the rslt list. */
		for ( int i = 0 ; i < (int)(*it)->getEdges().size() && done == false ; i++ )
		{
			if ( ! this->contains( (*it)->getIEdge(i)->getHead() ) )
			{
				rslt.push_back( (*it) );
				done = true;
			}
		}
	}
	
	return rslt;
}

list<Vertex*> Segment::getBoundary(int *_mark)
{
	list<Vertex*> rslt;
	
	/* We look at every vertices of the segment. */
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
		/* This boolean is created in order to avoid adding several times the same vertex to the rslt list. */
		bool done = false;
		
		/* If one neighbour of the vertex is not a part of the segment, it is a boundary vertex and we add it to the rslt list. */
		for ( int i = 0 ; i < (int)(*it)->getEdges().size() && done == false ; i++ )
		{
			if ( ! this->contains( (*it)->getIEdge(i)->getHead() ) )
			{
				rslt.push_back( (*it) );
				_mark[(*it)->getID()] = 0;
				done = true;
			}
		}
	}
	
	return rslt;
}

double Segment::getTriangulatedArea(Mesh _mesh)
{
	double rslt = 0;
	int* mark = (int*) calloc ( _mesh.getNFaces(), sizeof(int));
	
	/* We look at all the vertices componing the segment. */
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
		/* Now at all the faces related to this vertex. */
		/* So we look all the edges from this vertex. */
		for ( int i = 0 ; i < (int)(*it)->getEdges().size() ; i++ )
		{
			/* Finally we look the faces related to these edges. */
			for ( int j = 0 ; j < (int)(*it)->getIEdge(i)->getFaces().size() ; j++ )
			{
				/* If the face has'nt been marked yet. */
				if ( mark[ (*it)->getIEdge(i)->getIFace(j)->getID() ] == 0 )
				{
					/* We mark it. */
					mark[ (*it)->getIEdge(i)->getIFace(j)->getID() ] = 1;
					
					/* And we add to the rslt the area of this face. */
					rslt += (*it)->getIEdge(i)->getIFace(j)->triangulatedArea();
				}
			}
		}
	}
	
	/* Don't forget to free the memory. */
	free ( mark );
	
	return rslt;
}

double Segment::getTriangulatedArea(Mesh* _mesh)
{
	double rslt = 0;
	int* mark = (int*) calloc ( _mesh->getNFaces(), sizeof(int));
	
	/* We look at all the vertices componing the segment. */
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
		/* Now at all the faces related to this vertex. */
		/* So we look all the edges from this vertex. */
		for ( int i = 0 ; i < (int)(*it)->getEdges().size() ; i++ )
		{
			/* Finally we look the faces related to these edges. */
			for ( int j = 0 ; j < (int)(*it)->getIEdge(i)->getFaces().size() ; j++ )
			{
				/* If the face has'nt been marked yet. */
				if ( mark[ (*it)->getIEdge(i)->getIFace(j)->getID() ] == 0 )
				{
					/* We mark it. */
					mark[ (*it)->getIEdge(i)->getIFace(j)->getID() ] = 1;
					
					/* And we add to the rslt the area of this face. */
					rslt += (*it)->getIEdge(i)->getIFace(j)->triangulatedArea();
				}
			}
		}
	}
	
	/* Don't forget to free the memory. */
	free ( mark );
	
	return rslt;
}

double Segment::getTriangulatedAreaConverted(Mesh _mesh, double _areaMesh )
{
	double rslt = 0;
	int* mark = (int*) calloc ( _mesh.getNFaces(), sizeof(int));
	
	/* We look at all the vertices componing the segment. */
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
		/* Now at all the faces related to this vertex. */
		/* So we look all the edges from this vertex. */
		for ( int i = 0 ; i < (int)(*it)->getEdges().size() ; i++ )
		{
			/* Finally we look the faces related to these edges. */
			for ( int j = 0 ; j < (int)(*it)->getIEdge(i)->getFaces().size() ; j++ )
			{
				/* If the face has'nt been marked yet. */
				if ( mark[ (*it)->getIEdge(i)->getIFace(j)->getID() ] == 0 )
				{
					/* We mark it. */
					mark[ (*it)->getIEdge(i)->getIFace(j)->getID() ] = 1;
					
					/* And we add to the rslt the area of this face. */
					rslt += (*it)->getIEdge(i)->getIFace(j)->triangulatedArea();
				}
			}
		}
	}
	
	/* Don't forget to free the memory. */
	free ( mark );
	
	/* Then we interpolate the area. */
	rslt = (rslt * 100 ) / _areaMesh;
	return rslt;
}

double Segment::getTriangulatedAreaConverted(Mesh* _mesh, double _areaMesh )
{
	double rslt = 0;
	int* mark = (int*) calloc ( _mesh->getNFaces(), sizeof(int));
	
	/* We look at all the vertices componing the segment. */
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
		/* Now at all the faces related to this vertex. */
		/* So we look all the edges from this vertex. */
		for ( int i = 0 ; i < (int)(*it)->getEdges().size() ; i++ )
		{
			/* Finally we look the faces related to these edges. */
			for ( int j = 0 ; j < (int)(*it)->getIEdge(i)->getFaces().size() ; j++ )
			{
				/* If the face has'nt been marked yet. */
				if ( mark[ (*it)->getIEdge(i)->getIFace(j)->getID() ] == 0 )
				{
					/* We mark it. */
					mark[ (*it)->getIEdge(i)->getIFace(j)->getID() ] = 1;
					
					/* And we add to the rslt the area of this face. */
					rslt += (*it)->getIEdge(i)->getIFace(j)->triangulatedArea();
				}
			}
		}
	}
	
	/* Don't forget to free the memory. */
	free ( mark );
	
	/* Then we interpolate the area. */
	rslt = (rslt * 100 ) / _areaMesh;
		
	return rslt;
}

list<Vertex*>::iterator Segment::getBegin()
{
	return verts.begin();
}

list<Vertex*>::iterator Segment::getEnd()
{
	return verts.end();
}

void Segment::clear()
{
	id = 0;
	depth = 0;
	verts.clear();
}

void Segment::addVert(Vertex *_v)
{
	verts.push_back( _v );
}

void Segment::addSegment(Segment *_s)
{
	for ( list<Vertex*>::iterator it = _s->getBegin() ; it != _s->getEnd() ; it++ )
		if ( !contains( (*it) ) )
			addVert( (*it) );
}

void Segment::removeVert(Vertex *_v)
{
	verts.remove( _v );
}

void Segment::createFromSeed_Eq(Vertex *_seed, Mesh _mesh, Map _map)
{
	/* Launches a kind of breadth-first search algorithm from the seed vertex on the given mesh.
	   If one of the vertex in the Segment neighbourhood verify the criteria, it is added to the segment.
	   Else it is simlpy marked and non of its neighbours are added for searching.
	   See http://fr.wikipedia.org/wiki/Algorithme_de_parcours_en_largeur or http://en.wikipedia.org/wiki/Breadth-first_search for more
	   informations about the breadth-first searching algorithm. It should help understamnding the code of this methode.
	*/
	double			seedValue = _map.getIData( _seed->getID() );
	int				neighbourID = 0;
	int*			mark = (int*) calloc ( _mesh.getNVerts(), sizeof(int));		/* A marking array. */
	list<Vertex*>	list;
	
	depth = _map.getIData( _seed->getID() );
	
	/* Add the seed to the Segment */
	verts.clear();
	addVert( _seed );
	
	/* Add the seed to the list. */
	list.push_back( _seed );
	
	while ( !list.empty() )
	{
		/* While list is not empty. */
		Vertex* v = list.front();
		list.pop_front();
		
		/* We then search for every neighbour of v. */
		for ( int i = 0 ; i < (int)v->getEdges().size() ; i++ )
		{
			neighbourID = v->getIEdge(i)->getHead()->getID();
			/* If it is not marked, then we mark it and if it has the same value than the seed value, we add it to the list list. */
			if ( mark[ neighbourID ] == 0 )
			{
				mark[ neighbourID ] = 1;
				
				if ( _map.getIData( neighbourID ) == seedValue )
				{
					/* Adding the neighbour to the list list AND to the result segment. */
					list.push_back( v->getIEdge(i)->getHead() );
					addVert( v->getIEdge(i)->getHead() );
				}
			}
		}
	}
	
	free (mark);
}

void Segment::createFromSeed_Eq(Vertex *_seed, Mesh _mesh, Map _map, int *_mark)
{
	/* Launches a kind of breadth-first search algorithm from the seed vertex on the given mesh.
	   If one of the vertex in the Segment neighbourhood verify the criteria, it is added to the segment.
	   Else it is simlpy marked and non of its neighbours are added for searching.
	   See http://fr.wikipedia.org/wiki/Algorithme_de_parcours_en_largeur or http://en.wikipedia.org/wiki/Breadth-first_search for more
	   informations about the breadth-first searching algorithm. It should help understamnding the code of this methode.
	*/
	double			seedValue = _map.getIData( _seed->getID() );
	int				neighbourID = 0;
	int*			mark = (int*) calloc ( _mesh.getNVerts(), sizeof(int));		/* A marking array. */
	list<Vertex*>	list;
	
	depth = _map.getIData( _seed->getID() );
	_mark [ _seed->getID() ] = (int)depth;
	
	/* Add the seed to the Segment */
	verts.clear();
	addVert( _seed );
	
	/* Add the seed to the list. */
	list.push_back( _seed );
	
	while ( !list.empty() )
	{
		/* While list is not empty. */
		Vertex* v = list.front();
		list.pop_front();
		
		/* We then search for every neighbour of v. */
		for ( int i = 0 ; i < (int)v->getEdges().size() ; i++ )
		{
			neighbourID = v->getIEdge(i)->getHead()->getID();
			
			/* If it is not marked, then we mark it and if it has the same value than the seed value, we add it to the list list. */
			if ( mark[ neighbourID ] == 0 )
			{
				mark[ neighbourID ] = 1;
				
				if ( _map.getIData( neighbourID ) == seedValue )
				{
					/* Adding the neighbour to the list list AND to the result segment. */
					list.push_back( v->getIEdge(i)->getHead() );
					addVert( v->getIEdge(i)->getHead() );
					_mark[ v->getIEdge(i)->getHead()->getID() ] = (int)depth;
				}
			}
		}
	}
	
	free (mark);
}

void Segment::createFromSeed_GrEq(Vertex *_seed, Mesh _mesh, Map _map)
{
	/* Launches a kind of breadth-first search algorithm from the seed vertex on the given mesh.
	   If one of the vertex in the Segment neighbourhood verify the criteria, it is added to the segment.
	   Else it is simlpy marked and non of its neighbours are added for searching.
	   See http://fr.wikipedia.org/wiki/Algorithme_de_parcours_en_largeur or http://en.wikipedia.org/wiki/Breadth-first_search for more
	   informations about the breadth-first searching algorithm. It should help understamnding the code of this methode.
	*/
	double			seedValue = _map.getIData( _seed->getID() );
	int				neighbourID = 0;
	int*			mark = (int*) calloc ( _mesh.getNVerts(), sizeof(int));		/* A marking array. */
	list<Vertex*>	list;
	
	depth = _map.getIData( _seed->getID() );
	
	/* Add the seed to the Segment */
	verts.clear();
	addVert( _seed );
	
	/* Add the seed to the list. */
	list.push_back( _seed );
	
	while ( !list.empty() )
	{
		/* While list is not empty. */
		Vertex* v = list.front();
		list.pop_front();
		
		/* We then search for every neighbour of v. */
		for ( int i = 0 ; i < (int)v->getEdges().size() ; i++ )
		{
			neighbourID = v->getIEdge(i)->getHead()->getID();
			/* If it is not marked, then we mark it and if it has the same value than the seed value, we add it to the list list. */
			if ( mark[ neighbourID ] == 0 )
			{
				mark[ neighbourID ] = 1;
				
				if ( _map.getIData( neighbourID ) >= seedValue )
				{
					/* Adding the neighbour to the list list AND to the result segment. */
					list.push_back( v->getIEdge(i)->getHead() );
					addVert( v->getIEdge(i)->getHead() );
				}
			}
		}
	}
	
	free (mark);
}

void Segment::createFromSeed_GrEq(Vertex *_seed, Mesh _mesh, Map _map, int *_mark)
{
	/* Launches a kind of breadth-first search algorithm from the seed vertex on the given mesh.
	   If one of the vertex in the Segment neighbourhood verify the criteria, it is added to the segment.
	   Else it is simlpy marked and non of its neighbours are added for searching.
	   See http://fr.wikipedia.org/wiki/Algorithme_de_parcours_en_largeur or http://en.wikipedia.org/wiki/Breadth-first_search for more
	   informations about the breadth-first searching algorithm. It should help understamnding the code of this methode.
	*/
	double			seedValue = _map.getIData( _seed->getID() );
	int				neighbourID = 0;
	int*			mark = (int*) calloc ( _mesh.getNVerts(), sizeof(int));		/* A marking array. */
	list<Vertex*>	list;
	
	depth = _map.getIData( _seed->getID() );
	
	/* Add the seed to the Segment */
	verts.clear();
	addVert( _seed );
	
	/* Add the seed to the list. */
	list.push_back( _seed );
	
	while ( !list.empty() )
	{
		/* While list is not empty. */
		Vertex* v = list.front();
		list.pop_front();
		
		/* We then search for every neighbour of v. */
		for ( int i = 0 ; i < (int)v->getEdges().size() ; i++ )
		{
			neighbourID = v->getIEdge(i)->getHead()->getID();
			/* If it is not marked, then we mark it and if it has the same value than the seed value, we add it to the list list. */
			if ( mark[ neighbourID ] == 0 )
			{
				mark[ neighbourID ] = 1;
				
				if ( _map.getIData( neighbourID ) >= seedValue )
				{
					/* Adding the neighbour to the list list AND to the result segment. */
					list.push_back( v->getIEdge(i)->getHead() );
					addVert( v->getIEdge(i)->getHead() );
					_mark[ v->getIEdge(i)->getHead()->getID() ] = (int)depth;
				}
			}
		}
	}
	
	free (mark);
}

void Segment::createFromSeed_LeEq(Vertex *_seed, Mesh _mesh, Map _map)
{
	/* Launches a kind of breadth-first search algorithm from the seed vertex on the given mesh.
	   If one of the vertex in the Segment neighbourhood verify the criteria, it is added to the segment.
	   Else it is simlpy marked and non of its neighbours are added for searching.
	   See http://fr.wikipedia.org/wiki/Algorithme_de_parcours_en_largeur or http://en.wikipedia.org/wiki/Breadth-first_search for more
	   informations about the breadth-first searching algorithm. It should help understamnding the code of this methode.
	*/
	double			seedValue = _map.getIData( _seed->getID() );
	int				neighbourID = 0;
	int*			mark = (int*) calloc ( _mesh.getNVerts(), sizeof(int));		/* A marking array. */
	list<Vertex*>	list;
	
	depth = _map.getIData( _seed->getID() );
	
	/* Add the seed to the Segment */
	verts.clear();
	addVert( _seed );
	
	/* Add the seed to the list. */
	list.push_back( _seed );
	
	while ( !list.empty() )
	{
		/* While list is not empty. */
		Vertex* v = list.front();
		list.pop_front();
		
		/* We then search for every neighbour of v. */
		for ( int i = 0 ; i < (int)v->getEdges().size() ; i++ )
		{
			neighbourID = v->getIEdge(i)->getHead()->getID();
			
			/* If it is not marked, then we mark it and if it has the same value than the seed value, we add it to the list list. */
			if ( mark[ neighbourID ] == 0 )
			{
				mark[ neighbourID ] = 1;
				
				if ( _map.getIData( neighbourID ) <= seedValue )
				{
					/* Adding the neighbour to the list list AND to the result segment. */
					list.push_back( v->getIEdge(i)->getHead() );
					addVert( v->getIEdge(i)->getHead() );
				}
			}
		}
	}
	
	free (mark);
}

void Segment::createFromSeed_LeEq(Vertex *_seed, Mesh _mesh, Map _map, int *_mark)
{
	/* Launches a kind of breadth-first search algorithm from the seed vertex on the given mesh.
	   If one of the vertex in the Segment neighbourhood verify the criteria, it is added to the segment.
	   Else it is simlpy marked and non of its neighbours are added for searching.
	   See http://fr.wikipedia.org/wiki/Algorithme_de_parcours_en_largeur or http://en.wikipedia.org/wiki/Breadth-first_search for more
	   informations about the breadth-first searching algorithm. It should help understamnding the code of this methode.
	*/
	double			seedValue = _map.getIData( _seed->getID() );
	int				neighbourID = 0;
	int*			mark = (int*) calloc ( _mesh.getNVerts(), sizeof(int));		/* A marking array. */
	list<Vertex*>	list;
	
	this->setDepth( _map.getIData( _seed->getID() ) );
	
	/* Add the seed to the Segment */
	verts.clear();
	addVert( _seed );
	
	/* Add the seed to the list. */
	list.push_back( _seed );
	
	while ( !list.empty() )
	{
		/* While list is not empty. */
		Vertex* v = list.front();
		list.pop_front();
		
		/* We then search for every neighbour of v. */
		for ( int i = 0 ; i < (int)v->getEdges().size() ; i++ )
		{
			neighbourID = v->getIEdge(i)->getHead()->getID();
			
			/* If it is not marked, then we mark it and if it has the same value than the seed value, we add it to the list list. */
			if ( mark[ neighbourID ] == 0 )
			{
				mark[ neighbourID ] = 1;
				
				if ( _map.getIData( neighbourID ) <= seedValue )
				{
					/* Adding the neighbour to the list list AND to the result segment. */
					list.push_back( v->getIEdge(i)->getHead() );
					addVert( v->getIEdge(i)->getHead() );
					_mark[ neighbourID ] = (int)this->getDepth();
				}
			}
		}
	}
	
	free (mark);
}

void Segment::createFromSeed(int _criteria, Vertex *_seed, Mesh _mesh, Map _map)
{
	switch ( _criteria )
	{
		case EQUAL :
			createFromSeed_Eq( _seed, _mesh, _map );
			break;
		
		case GREATER_EQUAL :
			createFromSeed_GrEq( _seed, _mesh, _map );
			break;
		
		case LESSER_EQUAL :
			createFromSeed_LeEq( _seed, _mesh, _map );
			break;
		
		default :
			cout<<"Unknown criteria in the Segment::createFromSeed method"<<endl;
			cout<<"Segment creation aborted"<<endl;
			break;
	}
}

bool Segment::contains(Vertex *_v)
{
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
		if ( (*it) == _v )
			return true;
	}
	
	return false;
}

bool Segment::contains(int _vertID)
{
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
		if ( (*it)->getID() == _vertID )
			return true;
	}
	
	return false;
}

bool Segment::contains(Segment _s)
{
	for ( list<Vertex*>::iterator it = _s.verts.begin() ; it != _s.verts.end() ; it++ )
	{
		if ( ! this->contains( (*it) ) )
			return false;
	}
	
	return true;
}

bool Segment::contains(Segment* _s)
{
	for ( list<Vertex*>::iterator it = _s->verts.begin() ; it != _s->verts.end() ; it++ )
	{
			if ( ! this->contains( (*it) ) )
					return false;
	}

	return true;
}

bool Segment::intersects(Segment _s)
{
	/* For every vertex in the calling segment, we look if its ID is shared by _s. */
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
			if ( _s.contains( (*it)->getID() ) )
				return true;
	}

	return true;
}

bool Segment::intersects(Segment* _s)
{
	/* For every vertex in the calling segment, we look if its ID is shared by _s. */
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
			if ( _s->contains( (*it)->getID() ) )
				return true;
	}
	return false;
}

int Segment::intersectsQuantity(Segment _s)
{
	int cpt = 0;
	
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
			if ( _s.contains( (*it)->getID() ) )
				cpt++;
	}

	return cpt;
}

int Segment::intersectsQuantity(Segment* _s)
{
	int cpt = 0;
	
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
			if ( _s->contains( (*it)->getID() ) )
				cpt++;
	}
	
	return cpt;
}

void Segment::morphologicalDilatation( Mesh _mesh, int _size )
{
	/* Based on a breadth first search. See other methods to get more informations about it. */
	/* For example, the SegmentTreeList::getMatchBy_Distance method. */
	int* mark = (int*) malloc ( _mesh.getNVerts() * sizeof ( int ) );
	for ( int i = 0 ; i < _mesh.getNVerts() ; i++ )
		mark[i] = -1;
	
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
		mark[ (*it)->getID() ] = -2;
	
	list<Vertex*> bound = this->getBoundary( mark );
	
	while ( !bound.empty() )
	{
		/* While list is not empty. "Defiler la bound list". */
		Vertex* v = bound.front();
		bound.pop_front();
		
		/* If the vertex is not far away from the node's segment. */
		if ( mark[ v->getID() ] <= _size && mark[ v->getID() ] >= 0 )
		{
			/* We take a look at its neighbours. */
			for ( int i = 0 ; i < (int)v->getEdges().size() ; i++ )
			{
				Vertex* neighbour = v->getIEdge(i)->getHead();
			
				if ( mark [ neighbour->getID() ] == -1 )
				{
					
					/* We mark the vertex with its distance to the node's segment : the distance to v + 1 because it is v's neighbour. */
					mark[ neighbour->getID() ] = mark[ v->getID() ] + 1;
					
					/* We add the neighbour vertex to the list. */
					bound.push_back( neighbour );
					
					/* We add the neighbour to the current segent. */
					this->addVert( neighbour );
				}
			}
		}
	}
	
	/* Don't forget to free the allocated memory. */
	free ( mark );
}

void Segment::morphologicalDilatation( Mesh* _mesh, int _size )
{
	/* Based on a breadth first search. See other methods to get more informations about it. */
	/* For example, the SegmentTreeList::getMatchBy_Distance method. */
	int* mark = (int*) malloc ( _mesh->getNVerts() * sizeof ( int ) );
	for ( int i = 0 ; i < _mesh->getNVerts() ; i++ )
		mark[i] = -1;
	
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
		mark[ (*it)->getID() ] = -2;
	
	list<Vertex*> bound = this->getBoundary( mark );
	
	while ( !bound.empty() )
	{
		/* While list is not empty. "Defiler la bound list". */
		Vertex* v = bound.front();
		bound.pop_front();
		
		/* If the vertex is not far away from the node's segment. */
		if ( mark[ v->getID() ] <= _size && mark[ v->getID() ] >= 0 )
		{
			/* We take a look at its neighbours. */
			for ( int i = 0 ; i < (int)v->getEdges().size() ; i++ )
			{
				Vertex* neighbour = v->getIEdge(i)->getHead();
			
				if ( mark [ neighbour->getID() ] == -1 )
				{
					
					/* We mark the vertex with its distance to the node's segment : the distance to v + 1 because it is v's neighbour. */
					mark[ neighbour->getID() ] = mark[ v->getID() ] + 1;
					
					/* We add the neighbour vertex to the list. */
					bound.push_back( neighbour );
					
					/* We add the neighbour to the current segent. */
					this->addVert( neighbour );
				}
			}
		}
	}
	
	/* Don't forget to free the allocated memory. */
	free ( mark );
}

void Segment::morphologicalErosion(Mesh _mesh, int _size)
{
	/* Based on a breadth first search. See other methods to get more informations about it. */
	/* For example, the SegmentTreeList::getMatchBy_Distance method. */
	int* mark = (int*) malloc ( _mesh.getNVerts() * sizeof ( int ) );
	for ( int i = 0 ; i < _mesh.getNVerts() ; i++ )
		mark[i] = -2;
	
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
		mark[ (*it)->getID() ] = -1;
	
	list<Vertex*> bound = this->getBoundary( mark );
	
	for ( list<Vertex*>::iterator it = bound.begin() ; it != bound.end() ; it++ )
		this->removeVert( (*it) );
	
	while ( !bound.empty() )
	{
		/* While list is not empty. "Defiler la bound list". */
		Vertex* v = bound.front();
		bound.pop_front();
		
		/* If the vertex is not far away from the node's segment. */
		if ( mark[ v->getID() ] < _size && mark[ v->getID() ] >= 0 )
		{
			/* We take a look at its neighbours. */
			for ( int i = 0 ; i < (int)v->getEdges().size() ; i++ )
			{
				Vertex* neighbour = v->getIEdge(i)->getHead();
			
				if ( mark [ neighbour->getID() ] == -1 )
				{
					
					/* We mark the vertex with its distance to the node's segment : the distance to v + 1 because it is v's neighbour. */
					mark[ neighbour->getID() ] = mark[ v->getID() ] + 1;
					
					/* We add the neighbour vertex to the list. */
					bound.push_back( neighbour );
					
					/* We remove the neighbour from the current segent. */
					this->removeVert( neighbour );
				}
			}
		}
	}
	
	/* Don't forget to free the allocated memory. */
	free ( mark );
}

void Segment::morphologicalErosion(Mesh* _mesh, int _size)
{
	/* Based on a breadth first search. See other methods to get more informations about it. */
	/* For example, the SegmentTreeList::getMatchBy_Distance method. */
	int* mark = (int*) malloc ( _mesh->getNVerts() * sizeof ( int ) );
	for ( int i = 0 ; i < _mesh->getNVerts() ; i++ )
		mark[i] = -2;
	
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
		mark[ (*it)->getID() ] = -1;
	
	list<Vertex*> bound = this->getBoundary( mark );
	
	for ( list<Vertex*>::iterator it = bound.begin() ; it != bound.end() ; it++ )
		this->removeVert( (*it) );
	
	while ( !bound.empty() )
	{
		/* While list is not empty. "Defiler la bound list". */
		Vertex* v = bound.front();
		bound.pop_front();
		
		/* If the vertex is not far away from the node's segment. */
		if ( mark[ v->getID() ] < _size && mark[ v->getID() ] >= 0 )
		{
			/* We take a look at its neighbours. */
			for ( int i = 0 ; i < (int)v->getEdges().size() ; i++ )
			{
				Vertex* neighbour = v->getIEdge(i)->getHead();
			
				if ( mark [ neighbour->getID() ] == -1 )
				{
					
					/* We mark the vertex with its distance to the node's segment : the distance to v + 1 because it is v's neighbour. */
					mark[ neighbour->getID() ] = mark[ v->getID() ] + 1;
					
					/* We add the neighbour vertex to the list. */
					bound.push_back( neighbour );
					
					/* We remove the neighbour from the current segent. */
					this->removeVert( neighbour );
				}
			}
		}
	}
	
	/* Don't forget to free the allocated memory. */
	free ( mark );
}

void Segment::morphologicalOpening(Mesh _mesh, int _size)
{
	this->morphologicalErosion( _mesh, _size );
	this->morphologicalDilatation( _mesh, _size );
}

void Segment::morphologicalOpening(Mesh* _mesh, int _size)
{
	this->morphologicalErosion( _mesh, _size );
	this->morphologicalDilatation( _mesh, _size );
}

void Segment::morphologicalClosing(Mesh _mesh, int _size)
{
	this->morphologicalDilatation( _mesh, _size );
	this->morphologicalErosion( _mesh, _size );
}

void Segment::morphologicalClosing(Mesh* _mesh, int _size)
{
	this->morphologicalDilatation( _mesh, _size );
	this->morphologicalErosion( _mesh, _size );
}

void Segment::displayVertices(float _r, float _g, float _b)
{
	glColor3f ( _r, _g, _b );
	glBegin ( GL_POINTS );
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
		glNormal3dv( (*it)->getNormalArray() );
		glVertex3dv( (*it)->getPosArray() );
	}
	glEnd();
}

void Segment::displayVertices()
{
	glBegin ( GL_POINTS );
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
		glColor3dv( (*it)->getColorArray() );
		glNormal3dv( (*it)->getNormalArray() );
		glVertex3dv( (*it)->getPosArray() );
	}
	glEnd();
}

void Segment::displayEdges(float _r, float _g, float _b)
{
	glColor3f ( _r, _g, _b );
	glBegin ( GL_LINES );
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
		for ( int i = 0 ; i < (int)(*it)->getEdges().size() ; i++ )
		{
			/* We take a lookt at every neighbours of (*it). If it is in the Segment, we draw it, otherwise we don't. */
			Vertex* head = (*it)->getIEdge(i)->getHead();
			
			if ( contains( head ) )
			{
				/* The (*it) vertex is the tail of the edge. */
				glNormal3dv( (*it)->getNormalArray() );
				glVertex3dv( (*it)->getPosArray() );
				
				/* Now displayin the head. */
				glNormal3dv( head->getNormalArray() );
				glVertex3dv( head->getPosArray() );
			}
		}
	}
	glEnd();
}

void Segment::displayEdges()
{
	glBegin ( GL_LINES );
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
		for ( int i = 0 ; i < (int)(*it)->getEdges().size() ; i++ )
		{
			/* We take a lookt at every neighbours of (*it). If it is in the Segment, we draw it, otherwise we don't. */
			Vertex* head = (*it)->getIEdge(i)->getHead();
			
			if ( contains( head ) )
			{
				/* The (*it) vertex is the tail of the edge. */
				glColor3dv( (*it)->getColorArray() );
				glNormal3dv( (*it)->getNormalArray() );
				glVertex3dv( (*it)->getPosArray() );
				
				/* Now displayin the head. */
				glColor3dv( head->getColorArray() );
				glNormal3dv( head->getNormalArray() );
				glVertex3dv( head->getPosArray() );
			}
		}
	}
	glEnd();
}

void Segment::displayFaces(float _r, float _g, float _b)
{
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
		for ( int i = 0 ; i < (int)(*it)->getEdges().size() ; i++ )
		{
			/* We take a lookt at every neighbours of (*it). If it is in the Segment, we draw it, otherwise we don't. */
			Edge* e = (*it)->getIEdge(i);
			
			for ( int j = 0 ; j < (int)e->getFaces().size() ; j++ )
			{
				e->getIFace(j)->display( _r, _g, _b );
			}
		}
	}
}

void Segment::displayFaces()
{
	for ( list<Vertex*>::iterator it = verts.begin() ; it != verts.end() ; it++ )
	{
		for ( int i = 0 ; i < (int)(*it)->getEdges().size() ; i++ )
		{
			/* We take a lookt at every neighbours of (*it). If it is in the Segment, we draw it, otherwise we don't. */
			Edge* e = (*it)->getIEdge(i);
			
			for ( int j = 0 ; j < (int)e->getFaces().size() ; j++ )
			{
				e->getIFace(j)->display();
			}
		}
	}
}

void Segment::display(int _mode)
{
	switch ( _mode )
	{
		case VERTICES :
			displayVertices();
			break;
			
		case EDGES :
			displayEdges();
			break;
			
		case FACES :
			displayFaces();
			break;
		
		default :
			cout<<"Unknown mode selected in the Segment::display method"<<endl;
			cout<<"Segment not displayed"<<endl;
			break;
	}
}

void Segment::display(int _mode, float _r, float _g, float _b)
{
	switch ( _mode )
	{
		case VERTICES :
			displayVertices( _r, _g, _b );
			break;
			
		case EDGES :
			displayEdges( _r, _g, _b  );
			break;
			
		case FACES :
			displayFaces( _r, _g, _b  );
			break;
		
		default :
			cout<<"Unknown mode selected in the Segment::display method"<<endl;
			cout<<"Segment not displayed"<<endl;
			break;
	}
}
